Skip to content

Add property-based tests for API domain, policy, postage, receipt, id… - #1906

Merged
kryputh merged 1 commit into
Stellar-Mail:mainfrom
Emmy123222:test/property-based-api-generators
Jul 30, 2026
Merged

Add property-based tests for API domain, policy, postage, receipt, id…#1906
kryputh merged 1 commit into
Stellar-Mail:mainfrom
Emmy123222:test/property-based-api-generators

Conversation

@Emmy123222

Copy link
Copy Markdown
Contributor

Add property-based tests for Stellar addresses, hashes, amounts, timestamps, policies, postage, and receipts

Problem

The unit suite in tests/unit/api covers actor, domain, request, response, policy, postage, receipt, idempotency, and memory-repository behavior with example-based tests. Example tests can miss malformed Unicode, numeric boundaries, timestamp combinations, and unexpected object shapes that hand-picked examples don't happen to cover.

What this PR does

Adds fast-check as a devDependency and a shared arbitraries module (tests/unit/api/arbitraries.ts) that generates domain values mirroring the exact validation rules in src/server/api/domain.ts:

  • Stellar addresses — valid canonical G[A-Z2-7]{55} addresses, whitespace/case-variant addresses that normalize correctly, and structurally invalid addresses (wrong prefix, wrong length, disallowed base32 characters).
  • 32-byte hashes — valid/invalid hex hashes, including mixed-case normalization.
  • Amount strings — non-negative integer strings up to the Soroban i128 boundary (2^127 - 1), plus invalid variants (negative, one past the boundary, leading zeros, non-numeric).
  • Timestamps — UTC Z-suffixed instants (for postage.createdAt / idempotency records) versus offset-bearing instants (valid only for receipt fields), and receipt timestamp pairs that honor ordering + future-skew invariants.
  • Composite records — mailbox policies, postage, and receipts built from the primitives above.

New property-test files (49 new tests total):

File Covers
domain.properties.test.ts Schema accept/reject correctness, i128 boundary, receipt timestamp ordering and future-skew boundaries
policy-service.properties.test.ts evaluateMailboxPolicy decision table (allow/block/default rules) across arbitrary policy + postage + verification combinations
postage-service.properties.test.ts submitPostage minimum-postage enforcement and duplicate-messageId conflict, for arbitrary amounts
receipt-service.properties.test.ts Delivery-receipt idempotency, participant conflicts, concurrent-duplicate race safety, read-timestamp first-wins semantics
idempotency-service.properties.test.ts Key-hash determinism/sensitivity, canonical-digest order-independence, replay-once and payload-mismatch semantics
memory-repository.properties.test.ts Policy/postage round-trips, mutation isolation, sender-rule isolation, transitionPostage CAS races
actor.properties.test.ts Delegation authorization decision table (revoked/expiry/scope), delegation-issuance rules
response.properties.test.ts validateCorrelationId length boundary and disallowed-character rejection

Acceptance criteria

  • Generators cover valid and invalid values — every arbitrary above has a valid and an invalid counterpart, both exercised in tests.
  • Failures report reproducible seedsfast-check's default failure output includes { seed, path } plus a shrunk counterexample, so any CI failure can be reproduced locally by passing the same seed back into fc.assert.
  • Critical numeric and timestamp invariants are asserted — i128 boundary (±1), delivery/read timestamp ordering, 5-minute future-skew boundary (inclusive), CAS exactly-one-winner under concurrency.
  • The suite runs within a bounded CI timenumRuns is capped per property (60–200), and the full suite (151 files / 1766 tests, including these additions) runs in ~25–30s locally.

Verification

  • bun install (regenerated bun.lockb / package-lock.json with the new fast-check devDependency)
  • npx vitest run tests/unit — 151 files passed, 1766 tests passed, 3 expected fail (pre-existing)
  • npx tsc --noEmit — no errors
  • npx eslint tests/unit/api/arbitraries.ts tests/unit/api/*.properties.test.ts — no errors
  • Manually confirmed a deliberately-failing property reports a reproducible { seed, path } and shrunk counterexample

Files changed

New:

  • tests/unit/api/arbitraries.ts
  • tests/unit/api/actor.properties.test.ts
  • tests/unit/api/domain.properties.test.ts
  • tests/unit/api/idempotency-service.properties.test.ts
  • tests/unit/api/memory-repository.properties.test.ts
  • tests/unit/api/policy-service.properties.test.ts
  • tests/unit/api/postage-service.properties.test.ts
  • tests/unit/api/receipt-service.properties.test.ts
  • tests/unit/api/response.properties.test.ts

Modified:

  • package.json (added fast-check devDependency)
  • package-lock.json, bun.lockb

Closes #1553

…empotency, and repository invariants

Introduces fast-check as a devDependency and a shared arbitraries module
(tests/unit/api/arbitraries.ts) generating Stellar addresses, 32-byte hashes,
i128-bounded amount strings, and UTC/offset timestamps that mirror the exact
validation rules in src/server/api/domain.ts. New property suites exercise
valid and invalid generated inputs across stellarAddressSchema, hash32Schema,
stroopAmountSchema, mailboxPolicySchema, postageSchema, and receiptSchema
(ordering + future-skew boundaries), plus behavioral invariants in
evaluateMailboxPolicy, submitPostage, receipt delivery/read idempotency,
idempotency key hashing/canonicalization/replay semantics, MemoryApiRepository
round-trips and CAS races, and actor/delegation authorization.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@kryputh
kryputh merged commit eb9d9ea into Stellar-Mail:main Jul 30, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add property-based tests for shared API domain schemas

2 participants